home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / security / AccessController.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  15.0 KB  |  407 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)AccessController.java    1.45 98/09/11
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import sun.security.util.Debug;
  18.  
  19. /** 
  20.  * <p> The AccessController class is used for three purposes:
  21.  * 
  22.  * <ul>
  23.  * <li> to decide whether an access to a critical system
  24.  * resource is to be allowed or denied, based on the security policy
  25.  * currently in effect,<p> 
  26.  * <li>to mark code as being "privileged", thus affecting subsequent
  27.  * access determinations, and<p>
  28.  * <li>to obtain a "snapshot" of the current calling context so
  29.  * access-control decisions from a different context can be made with
  30.  * respect to the saved context. </ul>
  31.  * 
  32.  * <p> The {@link #checkPermission(Permission) checkPermission} method
  33.  * determines whether the access request indicated by a specified
  34.  * permission should be granted or denied. A sample call appears
  35.  * below. In this example, <code>checkPermission</code> will determine 
  36.  * whether or not to grant "read" access to the file named "testFile" in 
  37.  * the "/temp" directory.
  38.  * 
  39.  * <pre>
  40.  * 
  41.  *    FilePermission perm = new FilePermission("/temp/testFile", "read");
  42.  *    AccessController.checkPermission(perm);
  43.  * 
  44.  * </pre>
  45.  *
  46.  * <p> If a requested access is allowed, 
  47.  * <code>checkPermission</code> returns quietly. If denied, an 
  48.  * AccessControlException is
  49.  * thrown. AccessControlException can also be thrown if the requested
  50.  * permission is of an incorrect type or contains an invalid value.
  51.  * Such information is given whenever possible.
  52.  * 
  53.  * Suppose the current thread traversed m callers, in the order of caller 1 
  54.  * to caller 2 to caller m. Then caller m invoked the 
  55.  * <code>checkPermission</code> method.
  56.  * The <code>checkPermission </code>method determines whether access 
  57.  * is granted or denied based on the following algorithm:
  58.  * 
  59.  * <pre>
  60.  * i = m;
  61.  * 
  62.  * while (i > 0) {
  63.  * 
  64.  *      if (caller i's domain does not have the permission)
  65.  *              throw AccessControlException
  66.  * 
  67.  *      else if (caller i is marked as privileged) {
  68.  *              if (a context was specified in the call to doPrivileged) 
  69.  *                 context.checkPermission(permission)
  70.  *              return;
  71.  *      }
  72.  *      i = i - 1;
  73.  * };
  74.  *
  75.  *    // Next, check the context inherited when
  76.  *    // the thread was created. Whenever a new thread is created, the
  77.  *    // AccessControlContext at that time is
  78.  *    // stored and associated with the new thread, as the "inherited"
  79.  *    // context.
  80.  * 
  81.  * inheritedContext.checkPermission(permission);
  82.  * </pre>
  83.  * 
  84.  * <p> A caller can be marked as being "privileged" 
  85.  * (see {@link #doPrivileged(PrivilegedAction) doPrivileged} and below). 
  86.  * When making access control decisions, the <code>checkPermission</code>
  87.  * method stops checking if it reaches a caller that 
  88.  * was marked as "privileged" via a <code>doPrivileged</code> 
  89.  * call without a context argument (see below for information about a
  90.  * context argument). If that caller's domain has the
  91.  * specified permission, no further checking is done and 
  92.  * <code>checkPermission</code>
  93.  * returns quietly, indicating that the requested access is allowed.
  94.  * If that domain does not have the specified permission, an exception
  95.  * is thrown, as usual.
  96.  * 
  97.  * <p> The normal use of the "privileged" feature is as follows. If you
  98.  * don't need to return a value from within the "privileged" block, do 
  99.  * the following:
  100.  *
  101.  * <pre>
  102.  *   somemethod() {
  103.  *        ...normal code here...
  104.  *        AccessController.doPrivileged(new PrivilegedAction() {
  105.  *            public Object run() {
  106.  *                // privileged code goes here, for example:
  107.  *                System.loadLibrary("awt");
  108.  *                return null; // nothing to return
  109.  *            }
  110.  *        });
  111.   *       ...normal code here...
  112.  *  }
  113.  * </pre>
  114.  *
  115.  * <p>
  116.  * PrivilegedAction is an interface with a single method, named
  117.  * <code>run</code>, that returns an Object.
  118.  * The above example shows creation of an implementation
  119.  * of that interface; a concrete implementation of the
  120.  * <code>run</code> method is supplied.
  121.  * When the call to <code>doPrivileged</code> is made, an 
  122.  * instance of the PrivilegedAction implementation is passed
  123.  * to it. The <code>doPrivileged</code> method calls the
  124.  * <code>run</code> method from the PrivilegedAction 
  125.  * implementation after enabling privileges, and returns the 
  126.  * <code>run</code> method's return value as the 
  127.  * <code>doPrivileged</code> return value (which is
  128.  * ignored in this example).
  129.  *
  130.  * <p> If you need to return a value, you can do something like the following:
  131.  *
  132.  * <pre>
  133.  *   somemethod() {
  134.  *        ...normal code here...
  135.  *        String user = (String) AccessController.doPrivileged(
  136.  *          new PrivilegedAction() {
  137.  *            public Object run() {
  138.  *                return System.getProperty("user.name");
  139.  *            }
  140.  *          }
  141.  *        );
  142.  *        ...normal code here...
  143.  *  }
  144.  * </pre>
  145.  *
  146.  * <p>If the action performed in your <code>run</code> method could
  147.  * throw a "checked" exception (those listed in the <code>throws</code> clause
  148.  * of a method), then you need to use the 
  149.  * <code>PrivilegedExceptionAction</code> interface instead of the
  150.  * <code>PrivilegedAction</code> interface:
  151.  * 
  152.  * <pre>
  153.  *   somemethod() throws FileNotFoundException {
  154.  *        ...normal code here...
  155.  *      try {
  156.  *        FileInputStream fis = (FileInputStream) AccessController.doPrivileged(
  157.  *          new PrivilegedExceptionAction() {
  158.  *            public Object run() throws FileNotFoundException {
  159.  *                return new FileInputStream("someFile");
  160.  *            }
  161.  *          }
  162.  *        );
  163.  *      } catch (PrivilegedActionException e) {
  164.  *        // e.getException() should be an instance of FileNotFoundException,
  165.  *        // as only "checked" exceptions will be "wrapped" in a
  166.  *        // <code>PrivilegedActionException</code>.
  167.  *        throw (FileNotFoundException) e.getException();
  168.  *      }
  169.  *        ...normal code here...
  170.  *  }
  171.  * </pre>
  172.  * 
  173.  * <p> Be *very* careful in your use of the "privileged" construct, and 
  174.  * always remember to make the privileged code section as small as possible.
  175.  * 
  176.  * <p> Note that <code>checkPermission</code> always performs security checks
  177.  * within the context of the currently executing thread.
  178.  * Sometimes a security check that should be made within a given context
  179.  * will actually need to be done from within a
  180.  * <i>different</i> context (for example, from within a worker thread).
  181.  * The {@link #getContext() getContext} method and 
  182.  * AccessControlContext class are provided 
  183.  * for this situation. The <code>getContext</code> method takes a "snapshot"
  184.  * of the current calling context, and places
  185.  * it in an AccessControlContext object, which it returns. A sample call is
  186.  * the following:
  187.  * 
  188.  * <pre>
  189.  * 
  190.  *   AccessControlContext acc = AccessController.getContext()
  191.  * 
  192.  * </pre>
  193.  * 
  194.  * <p>
  195.  * AccessControlContext itself has a <code>checkPermission</code> method
  196.  * that makes access decisions based on the context <i>it</i> encapsulates,
  197.  * rather than that of the current execution thread.
  198.  * Code within a different context can thus call that method on the
  199.  * previously-saved AccessControlContext object. A sample call is the
  200.  * following:
  201.  * 
  202.  * <pre>
  203.  * 
  204.  *   acc.checkPermission(permission)
  205.  * 
  206.  * </pre> 
  207.  *
  208.  * <p> There are also times where you don't know a priori which permissions
  209.  * to check the context against. In these cases you can use the
  210.  * doPrivileged method that takes a context:
  211.  * 
  212.  * <pre>
  213.  *   somemethod() {
  214.  *         AccessController.doPrivileged(new PrivilegedAction() {
  215.  *              public Object run() {
  216.  *                 // Code goes here. Any permission checks from this
  217.  *                 // point forward require both the current context and
  218.  *                 // the snapshot's context to have the desired permission.
  219.  *              }
  220.  *         }, acc);
  221.  *         ...normal code here...
  222.  *   }
  223.  * </pre>
  224.  * 
  225.  * @see AccessControlContext
  226.  *
  227.  * @version 1.45 98/09/11
  228.  * @author Li Gong 
  229.  * @author Roland Schemers
  230.  */
  231.  
  232. public final class AccessController {
  233.  
  234.     /** 
  235.      * Don't allow anyone to instantiate an AccessController
  236.      */
  237.     private AccessController() { }
  238.  
  239.     /**
  240.      * Performs the specified <code>PrivilegedAction</code> with privileges
  241.      * enabled. The action is performed with <i>all</i> of the permissions 
  242.      * possessed by the caller's protection domain.
  243.      * <p>
  244.      * If the action's <code>run</code> method throws an (unchecked) exception,
  245.      * it will propagate through this method.
  246.      *
  247.      * @param action the action to be performed.
  248.      * @return the value returned by the action's <code>run</code> method.
  249.      * @see #doPrivileged(PrivilegedAction,AccessControlContext)
  250.      * @see #doPrivileged(PrivilegedExceptionAction)
  251.      */
  252.  
  253.     public static native Object doPrivileged(PrivilegedAction action);
  254.  
  255.  
  256.     /**
  257.      * Performs the specified <code>PrivilegedAction</code> with privileges
  258.      * enabled and restricted by the specified <code>AccessControlContext</code>.
  259.      * The action is performed with the intersection of the permissions
  260.      * possessed by the caller's protection domain, and those possessed
  261.      * by the domains represented by the specified
  262.      * <code>AccessControlContext</code>.
  263.      * <p>
  264.      * If the action's <code>run</code> method throws an (unchecked) exception,
  265.      * it will propagate through this method.
  266.      *
  267.      * @param action the action to be performed.
  268.      * @param context an <i>access control context</i> representing the
  269.      *              restriction to be applied to the caller's domain's
  270.      *              privileges before performing the specified action.
  271.      * @return the value returned by the action's <code>run</code> method.
  272.      * @see #doPrivileged(PrivilegedAction)
  273.      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  274.      */
  275.     public static native Object doPrivileged(PrivilegedAction action,
  276.                        AccessControlContext context);
  277.  
  278.     /**
  279.      * Performs the specified <code>PrivilegedExceptionAction</code> with
  280.      * privileges enabled.  The action is performed with <i>all</i> of the 
  281.      * permissions possessed by the caller's protection domain.
  282.      * <p>
  283.      * If the action's <code>run</code> method throws an <i>unchecked</i>
  284.      * exception, it will propagate through this method.
  285.      *
  286.      * @param action the action to be performed.
  287.      * @return the value returned by the action's <code>run</code> method.
  288.      * @throws PrivilgedActionException the specified action's
  289.      *         <code>run</code> method threw a <i>checked</i> exception.
  290.      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  291.      * @see #doPrivileged(PrivilegedAction)
  292.      */
  293.     public static native Object doPrivileged(PrivilegedExceptionAction action)
  294.      throws PrivilegedActionException;
  295.  
  296.  
  297.     /**
  298.      * Performs the specified <code>PrivilegedExceptionAction</code> with 
  299.      * privileges enabled and restricted by the specified
  300.      * <code>AccessControlContext</code>.  The action is performed with the
  301.      * intersection of the the permissions possessed by the caller's
  302.      * protection domain, and those possessed by the domains represented by the
  303.      * specified <code>AccessControlContext</code>.
  304.      * <p>
  305.      * If the action's <code>run</code> method throws an <i>unchecked</i>
  306.      * exception, it will propagate through this method.
  307.      *
  308.      * @param action the action to be performed.
  309.      * @param context an <i>access control context</i> representing the
  310.      *              restriction to be applied to the caller's domain's
  311.      *              privileges before performing the specified action.
  312.      * @return the value returned by the action's <code>run</code> method.
  313.      * @throws PrivilegedActionException the specified action's
  314.      *         <code>run</code> method
  315.      *           threw a <i>checked</i> exception.
  316.      * @see #doPrivileged(PrivilegedAction)
  317.      * @see #doPrivileged(PrivilegedExceptionAction,AccessControlContext)
  318.      */
  319.     public static native Object doPrivileged(PrivilegedExceptionAction action,
  320.                        AccessControlContext context)
  321.      throws PrivilegedActionException;
  322.  
  323.     /**
  324.      * Returns the AccessControl context. i.e., it gets 
  325.      * the protection domains of all the callers on the stack,
  326.      * starting at the first class with a non-null 
  327.      * ProtectionDomain. 
  328.      *
  329.      * @return the access control context based on the current stack or
  330.      *         null if there was only privileged system code.
  331.      * 
  332.      * 
  333.      */
  334.  
  335.     private static native AccessControlContext getStackAccessControlContext();
  336.  
  337.     /**
  338.      * Returns the "inherited" AccessControl context. This is the context
  339.      * that existed when the thread was created. Package private so 
  340.      * AccessControlContext can use it.
  341.      */
  342.  
  343.     static native AccessControlContext getInheritedAccessControlContext();
  344.  
  345.     /** 
  346.      * This method takes a "snapshot" of the current calling context, which
  347.      * includes the current Thread's inherited AccessControlContext,
  348.      * and places it in an AccessControlContext object. This context may then
  349.      * be checked at a later point, possibly in another thread.
  350.      *
  351.      * @see AccessControlContext
  352.      *
  353.      * @return the AccessControlContext based on the current context.
  354.      */
  355.  
  356.     public static AccessControlContext getContext()
  357.     {
  358.     AccessControlContext acc = getStackAccessControlContext();
  359.     if (acc == null) {
  360.         // all we had was privileged system code. We don't want
  361.         // to return null though, so we construct a real ACC.
  362.         return new AccessControlContext(null, true);
  363.     } else {
  364.         return acc.optimize();
  365.     }
  366.     }
  367.  
  368.     /** 
  369.      * Determines whether the access request indicated by the
  370.      * specified permission should be allowed or denied, based on
  371.      * the security policy currently in effect. 
  372.      * This method quietly returns if the access request
  373.      * is permitted, or throws a suitable AccessControlException otherwise. 
  374.      *
  375.      * @param perm the requested permission.
  376.      * 
  377.      * @exception AccessControlException if the specified permission
  378.      * is not permitted, based on the current security policy.
  379.      */
  380.  
  381.     public static void checkPermission(Permission perm)
  382.          throws AccessControlException 
  383.     {
  384.     //System.err.println("checkPermission "+perm);
  385.     //Thread.currentThread().dumpStack();
  386.  
  387.     AccessControlContext stack = getStackAccessControlContext();
  388.     // if context is null, we had privileged system code on the stack.
  389.     if (stack == null) {
  390.         Debug debug = AccessControlContext.getDebug();
  391.         if (debug != null) {
  392.         if (Debug.isOn("stack"))
  393.             Thread.currentThread().dumpStack();
  394.         if (Debug.isOn("domain")) {
  395.             debug.println("domain (context is null)");
  396.         }
  397.         debug.println("access allowed "+perm);
  398.         }
  399.         return;
  400.     }
  401.  
  402.     AccessControlContext acc = stack.optimize();
  403.     acc.checkPermission(perm);
  404.  
  405.     }
  406. }
  407.